#ifndef _ATOMIC_H_
#define _ATOMIC_H_
 
#include <stdio.h>
 
namespace utillib
{
	namespace util
	{
#ifdef WIN32
#include <windows.h>
 
typedef __int64		__INT64;
		static inline __INT64 CAS64(volatile __INT64 *target, __INT64 exchange, __INT64 comparand)
		{    
			BOOL result = TRUE;
			__asm
			{        
				push ecx
				push ebx
				push eax
				push edx
				push edi

				mov edx, dword ptr [ comparand ] + 4
				mov eax, dword ptr [ comparand ]
				mov ecx, dword ptr [ exchange ] + 4
				mov ebx, dword ptr [ exchange ]
				mov edi, target
				lock cmpxchg8b qword ptr [ edi ]

				pop edi
				pop edx
				pop eax
				pop ebx
				pop ecx
				je    success
				mov dword ptr [result], 0        
		success:
			}
			if ( result == TRUE )
				return ( comparand );
			else return ( *target );
		}
#else		// No Windows For Linux

		typedef long long		__INT64;
		 
		static inline long InterlockedIncrement( volatile long *value )
		{
			long returnValue;
		 
			__asm__ volatile
			(	
				"lock xaddl %1, (%2)\n\t"
				"incl %1\n\t"
				:	"=a" (returnValue)
				:	"0"(1), "r"(value)
				:	"memory"
			);
			return returnValue;
		}
		 
		static inline long InterlockedDecrement( volatile long *value )
		{
			long returnValue;
		 
			__asm__ volatile
			(
				 "lock xaddl %1, (%2)\n\t"
				 "incl %1\n\t"
				 :	"=a" (returnValue)
				 :	"0"(-1), "r"(value)
				 :	"memory"
			);
			return returnValue;
		}  
		 
		static inline long InterlockedExchangeIncrement( volatile long *value )
		{
			long returnValue;
		 
			__asm__ volatile
			(
				 "lock xaddl %1, (%2)\n\t"
				 :	"=a" (returnValue)
				 :	"0"(1), "r"(value)
				 :	"memory"
			);
			return returnValue;
		}
		 
		static inline long InterlockedExchangeDecrement( volatile long *value )
		{
			long returnValue;
		 
			__asm__ volatile
			(   
				 "lock xaddl %1, (%2)\n\t"
				 :	"=a" (returnValue)
				 :	"0"(-1), "r"(value)
				 :	"memory"
			);  
			return returnValue;
		}
		 
		static inline long InterlockedExchangeAdd( volatile long *value, long addValue )
		{
			long returnValue;
		 
			__asm__ volatile
			(
				 "lock xaddl %1, (%2)\n\t"
				 :	"=a" (returnValue)
				 :	"0"(addValue), "r"(value)
				 :	"memory"
			);
			return returnValue;
		}  
		 
		static inline __INT64 InterlockedExchangeIncrement64( volatile __INT64 *value )
		{
			__INT64 returnValue;
		 
			__asm__ volatile
			(   
				 "lock xaddq %1, (%2)\n\t"
				 :	"=a" (returnValue)
				 :	"0"(1LL), "r"(value)
				 :	"memory"
			);  
			return returnValue;
		}
		 
		static inline __INT64 InterlockedExchangeDecrement64( volatile __INT64 *value )
		{
			__INT64 returnValue;
		 
			__asm__ volatile
			(   
				 "lock xaddq %1, (%2)\n\t"
				 :	"=a" (returnValue)
				 :	"0"(-1LL), "r"(value)
				 :	"memory"
			);  
			return returnValue;
		}
		 
		static inline __INT64 InterlockedExchangeAdd64( volatile __INT64 *value, __INT64 addValue )
		{
			__INT64 returnValue;
		 
			__asm__ volatile
			(   
				 "lock xaddq %1, (%2)\n\t"
				 :	"=a" (returnValue)
				 :	"0"(addValue), "r"(value)
				 :	"memory"
			);  
			return returnValue;
		}
		 
		static inline long InterlockedExchange( volatile long *target, long value )
		{
			long returnValue;
		 
			__asm__ volatile
			(
				"lock xchgl %1, (%2)"
				:	"=a" (returnValue)
				:	"0"(value), "r"(target)
				:	"memory"
			);
			return returnValue;
		}
		 
		static inline long InterlockedCompareExchange( volatile long *target, long exchange, long comparand )
		{
			long returnValue;
		 
			__asm__ volatile
			(
				 "lock cmpxchgl %1, (%2)"
				 :	"=a" (returnValue)
				 :	"r" (exchange), "r" (target), "0"(comparand)
				 :	"memory"
			);
			return returnValue;
		}
		 
		static inline __INT64 InterlockedCompareExchange( volatile __INT64 *target, long exchange, long exchange2, long comparand, long comparand2 )
		{
			__INT64 returnValue;
			__asm__ volatile
			(
				 "lock cmpxchg8b %1"
				 :   "=A" (returnValue), "=m" (*target)
				 :   "b" (exchange),
					 "c" (exchange2),
					 "m" (*target),
					 "a" (comparand),
					 "d" (comparand2)
				 :   "memory"
			);
		 
			return returnValue;
		}
		 
		#define		CAS64(__target__, __exchange__, __comparand__ ) \
						InterlockedCompareExchange( __target__ ,\
													( ( long )( __exchange__ & 0xffffffff ) ) ,\
													( ( long )( __exchange__ >> 32 ) )	,\
													( ( long )( __comparand__ & 0xffffffff ) )	,\
													( ( long )( __comparand__ >> 32 ) ) )	
		/*
		static inline __INT64 CAS64( volatile __INT64 *target, __INT64 exchange, __INT64 comparand )
		{
			__INT64 returnValue;
			__asm__ volatile
			(
				"lock cmpxchg8b %1"			     
				:	"=A" (returnValue), "=m" (*target)			     
				:	"b" ((long)(exchange & 0xffffffff)),				     
					"c" ((long)(exchange >> 32)),
					"m" (*target), 
					"a" ((long)(comparand & 0xffffffff)),		      
					"d" ((long)(comparand >> 32)) 
				:	"memory"
			);
			__asm__ __volatile__
			(
				 "lock cmpxchgq %1,%2 \n\t"
				 :	"=a" (returnValue)
				 :	"q" (exchange), "m"(*(volatile __INT64 *)target), "a"(comperand)
				 :	"memory"
			);
			return returnValue;
		}
		*/
#endif
	}
}
 
#endif
